﻿
/*
 * Copyright (C) Han Wei
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;
using System.Threading;

using Thrift.Server;
using log4net;
using BSvr.PluginAPI;
using Thrift.Transport;
using System.Reflection;
using BSvr.Model;
using System.Runtime.Remoting;


namespace BSvr.Server
{
    /// <summary>
    /// 后台服务器
    /// </summary>
    class Server
    {
        private static ILog loger = log4net.LogManager.GetLogger(typeof(Server));

        TServer server = null;
        Thread svrThrd = null;
        string _pluginBaseDir = "plugin";                           // 插件基目录
        Dictionary<string, PluginDomain> iPlugin = null;            // 已加载插件集合
        
        /// <summary>
        /// 批处理器设置
        /// </summary>
        internal KeyValueConfigurationCollection PluginSettings
        {
            get
            {
                System.Configuration.Configuration config =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

                //Get the appSettings section.
                AppSettingsSection appSettings =
                    (AppSettingsSection)config.GetSection("pluginSettings");
                if (appSettings != null)
                {
                    return appSettings.Settings;
                }
                else
                {
                    return new KeyValueConfigurationCollection();
                }
            }
        }
        
        /// <summary>
        /// 批处理器
        /// </summary>
        internal Dictionary<string, PluginDomain> Plugins
        {
            get
            {
                if (iPlugin == null)
                    iPlugin = new Dictionary<string, PluginDomain>();
                return iPlugin;
            }
        }

        /// <summary>
        /// 线程方法
        /// </summary>
        private void _Start()
        {
            try
            {
                server.Serve();                     // 启动网络模块
            }
            catch (Exception ex)
            {
                loger.Error("网络启动异常", ex);
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            loger.Info("开始初始化服务器");
            try
            {
                string m_plugindir = System.Configuration.ConfigurationManager.AppSettings["PluginDir"];
                if (!string.IsNullOrEmpty(m_plugindir))
                    _pluginBaseDir = m_plugindir;

                LoadPlugins();              // 准备业务模块
                
                /* 准备网络模块 */
                BatchChannel.Processor processor = new BatchChannel.Processor(new BatchProcess(this));
                int port = int.Parse(System.Configuration.ConfigurationManager.AppSettings["ServerPort"]);
                TServerTransport serverTransport = new TServerSocket(port);
                server = new TThreadPoolServer(processor, serverTransport);

                loger.Info("初始化成功"); 
            }
            catch (Exception ex)
            {
                loger.Error("初始化异常", ex);
                System.Console.WriteLine("初始化失败");
            }
        }

        /// <summary>
        /// 启动
        /// </summary>
        public void Start()
        {
            loger.Info("开始启动服务器");
            try
            {
                foreach (KeyValuePair<string, PluginDomain> item in this.Plugins)                               // 启动已经加载的业务
                {
                    try {
                        OpRst<string> srst = item.Value.Start();
                        if (!srst.IsSuccess)
                        {
                            System.Console.WriteLine("业务" + item.Key + "启动失败，失败原因：" + srst.Result);
                        }
                        else
                        {
                            System.Console.WriteLine("业务" + item.Key + "启动成功");
                        }
                    }
                    catch (Exception ex) {
                        System.Console.WriteLine("业务" + item.Key + "启动异常，异常原因："+ex.Message);
                        loger.Error(ex);
                    }
                }

                svrThrd = new System.Threading.Thread(new System.Threading.ThreadStart(this._Start));           // 服务线程启动
                svrThrd.Start();

                System.Console.WriteLine("启动完成");
            }
            catch (Exception ex)
            {
                loger.Error("启动异常", ex);
                System.Console.WriteLine("启动异常，异常原因："+ex.Message);
            }

        }

        /// <summary>
        /// 终止
        /// </summary>
        public void End()
        {
            loger.Info("开始终止服务器运行");
            try
            {
                // 终止网络模块
                server.Stop();
            }
            catch { }

            foreach (KeyValuePair<string, PluginDomain> item in this.Plugins)
            {
                try
                {
                    item.Value.UnLoad();
                }
                catch (Exception ex)
                {
                    loger.Error(ex);
                }
            }
            try
            {
                svrThrd.Abort();
            }
            catch { }

            loger.Info("终止成功");
            System.Console.WriteLine("终止成功");
        }

        /// <summary>
        /// 执行指定的命令,由控制台执行
        /// </summary>
        /// <param name="args"></param>
        public void Excute(string[] args)
        {
            if (args.Length == 0)
                throw new ArgumentNullException("没有命令参数");

            string cmd = args[0].Trim().ToLower();
            switch (cmd) {
                case "help":                                    // 显示帮助，服务器所支持的所有命令，不包含业务系统支持的命令
                    {
                        System.Console.WriteLine(Help(""));
                    }
                    break;
                case "info":
                    {
                        if (args.Length == 2 && args[1] == "--help")
                        {
                            System.Console.WriteLine(Help("info"));
                            return;
                        }

                        System.Console.WriteLine("  当前版本为V1.1.1，本版本增加了如下功能：");
                        System.Console.WriteLine("      1、运行时隔离业务插件");
                        System.Console.WriteLine("      2、运行时加载业务插件");
                        System.Console.WriteLine("      3、运行时卸载业务插件");
                        System.Console.WriteLine("      4、修复了远程对象生存周期bug");
                    }
                    break;
                case "loading":                                 // 显示所有已经加载的业务插件
                    {
                        if (args.Length == 2 && args[1] == "--help")
                        {
                            System.Console.WriteLine(Help("loading"));
                            return;
                        }

                        Loading();
                    }
                    break;
                case "load":                                    // 动态加载业务插件
                    {
                        if (args.Length == 2 && args[1] == "--help")
                        {
                            System.Console.WriteLine(Help("load"));
                            return;
                        }

                        if (args.Length < 3)
                        {
                            System.Console.WriteLine("load命令需要两个参数");
                            return;
                        }

                        string pluginno = args[1];
                        string plugindir = args[2];

                        try
                        {
                            OpRst<string> lorst = LoadPlugin(pluginno, plugindir);
                            if (lorst.IsSuccess)
                            {
                                System.Console.WriteLine("加载成功");
                            }
                            else
                                System.Console.WriteLine("业务加载失败，失败原因:" + lorst.Result);
                        }
                        catch (Exception ex)
                        {
                            loger.Error(ex);
                            System.Console.WriteLine("业务加载失败");
                        }
                    }
                    break;
                case "unload":
                    {
                        if (args.Length == 2 && args[1] == "--help")
                        {
                            System.Console.WriteLine(Help("unload"));
                            return;
                        }

                        if (args.Length < 2)
                        {
                            System.Console.WriteLine("unload命令需要1个参数");
                        }

                        string pluginno = args[1];

                        try
                        {
                            OpRst<string> lorst = UnLoadPlugin(pluginno);
                            if (lorst.IsSuccess)
                                System.Console.WriteLine("卸载加载成功");
                            else
                                System.Console.WriteLine("业务卸载失败，失败原因:" + lorst.Result);
                        }
                        catch (Exception ex)
                        {
                            loger.Error(ex);
                            System.Console.WriteLine("业务卸载异常，异常原因："+ex.Message);
                        }
                    }
                    break;
                case "start":
                    {
                        if (args.Length == 2 && args[1] == "--help")
                        {
                            System.Console.WriteLine(Help("start"));
                            return;
                        }

                        if (args.Length < 2)
                        {
                            System.Console.WriteLine("start命令需要1个参数");
                        }

                        string pluginno = args[1];
                        if (this.Plugins.Keys.Contains(pluginno))
                        {
                            if (this.Plugins[pluginno].Running)
                            {
                                System.Console.WriteLine("该业务已经启动");
                                return;
                            }
                            try
                            {
                                OpRst<string> lorst = this.Plugins[pluginno].Start();
                                if (lorst.IsSuccess)
                                    System.Console.WriteLine("启动成功");
                                else
                                    System.Console.WriteLine("业务启动失败，失败原因:" + lorst.Result);
                            }
                            catch (Exception ex)
                            {
                                loger.Error(ex);
                                System.Console.WriteLine("业务启动异常，异常原因：" + ex.Message);
                            }
                        }
                        else
                        {
                            System.Console.WriteLine("没有该业务");
                        }
                    }
                    break;
                case "end":
                    {
                        if (args.Length == 2 && args[1] == "--help")
                        {
                            System.Console.WriteLine(Help("end"));
                            return;
                        }

                        if (args.Length < 2)
                        {
                            System.Console.WriteLine("end命令需要1个参数");
                        }

                        string pluginno = args[1];
                        if (this.Plugins.Keys.Contains(pluginno))
                        {
                            if (!this.Plugins[pluginno].Running)
                            {
                                System.Console.WriteLine("该业务已经关闭");
                                return;
                            }
                            try
                            {
                                OpRst<string> lorst = this.Plugins[pluginno].Start();
                                if (lorst.IsSuccess)
                                    System.Console.WriteLine("关闭成功");
                                else
                                    System.Console.WriteLine("业务关闭失败，失败原因:" + lorst.Result);
                            }
                            catch (Exception ex)
                            {
                                loger.Error(ex);
                                System.Console.WriteLine("业务关闭异常，异常原因：" + ex.Message);
                            }
                        }
                        else
                        {
                            System.Console.WriteLine("没有该业务");
                        }
                    }
                    break;

            }
        }

        #region 命令处理方法
        /// <summary>
        /// 显示所有已经加载的业务插件
        /// </summary>
        private void Loading() {
            int row = System.Console.CursorTop;
            List<int> cols = new List<int>();                   // 存放标题光标的列位置
            System.Console.Write("  ");
            cols.Add(System.Console.CursorLeft);
            System.Console.Write("业务编号              ");
            cols.Add(System.Console.CursorLeft);
            System.Console.Write("业务目录              ");
            cols.Add(System.Console.CursorLeft);
            System.Console.Write("是否加载              ");
            cols.Add(System.Console.CursorLeft);
            System.Console.Write("是否启动");
            cols.Add(System.Console.CursorLeft);
            System.Console.WriteLine("");
            row++;

            for(int i=0;i<cols[4]+2;i++)
                System.Console.Write("-");

            System.Console.WriteLine("");
            row++;
            
            foreach (KeyValuePair<string, PluginDomain> item in Plugins)
            {
                row++;
                System.Console.SetCursorPosition(cols[0], row);
                System.Console.Write(item.Key);
                System.Console.SetCursorPosition(cols[1], row);
                string[] path = item.Value.PluginPath.Split(new char[] { '\\' },StringSplitOptions.RemoveEmptyEntries);
                System.Console.Write(path[path.Length-1]);
                System.Console.SetCursorPosition(cols[2], row);
                System.Console.Write(item.Value.Loaded.ToString());
                System.Console.SetCursorPosition(cols[3], row);
                System.Console.WriteLine(item.Value.Running.ToString()); 
            }
        }

        /// <summary>
        /// 加载业务模块
        /// </summary>
        /// <param name="pluginno">插件编号</param>
        /// <param name="pluginpath">插件路径</param>
        /// <returns></returns>
        private OpRst<string> LoadPlugin(string pluginno, string plugindir)
        {
            if (this.Plugins.Keys.Contains(pluginno))
                return new OpRst<string>(false, "存在同名的插件编号");

            try
            {
                string bp = (System.AppDomain.CurrentDomain.BaseDirectory.EndsWith("\\") ? System.AppDomain.CurrentDomain.BaseDirectory : (System.AppDomain.CurrentDomain.BaseDirectory+"\\"));
                string pp = bp + this._pluginBaseDir+"\\" + plugindir;

                PluginDomain domain = new PluginDomain(pluginno, bp, pp);
                OpRst<string> lrst = domain.Load();
                if (lrst.IsSuccess)
                {
                    this.Plugins.Add(pluginno, domain);
                    return lrst;
                }
                else
                {
                    return lrst;
                }
            }
            catch (Exception ex) {
                loger.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 服务器启动时，加载一批插件
        /// </summary>
        private void LoadPlugins() {
            foreach (KeyValueConfigurationElement item in this.PluginSettings) {
                try
                {
                    OpRst<string> lorst = LoadPlugin(item.Key, item.Value);
                    if (lorst.IsSuccess)
                        System.Console.WriteLine("业务"+item.Key+"加载成功");
                    else
                        System.Console.WriteLine("业务"+item.Key+"加载失败，失败原因:" + lorst.Result);
                }
                catch (Exception ex)
                {
                    loger.Error(ex);
                    System.Console.WriteLine("业务" + item.Key + "加载失败");
                }
            }
        }

        /// <summary>
        /// 卸载业务模块
        /// </summary>
        /// <param name="pluginno">插件编号</param>
        /// <returns></returns>
        private OpRst<string> UnLoadPlugin(string pluginno) {
            if (!this.Plugins.Keys.Contains(pluginno))
                return new OpRst<string>(false, "不存在该插件");

            try {
                PluginDomain mydomain =  this.Plugins[pluginno];
                this.Plugins.Remove(pluginno);
                return mydomain.UnLoad();
            }
            catch (Exception ex) {
                throw ex;
            }
        }

        /// <summary>
        /// 获取命令的帮助
        /// </summary>
        /// <param name="cmd">命令，空命令表示显示所有帮助</param>
        /// <returns>命令帮助</returns>
        private string Help(string cmd) {
            StringBuilder sb = new StringBuilder();
            string helppath = "help.txt";
            if (File.Exists(helppath))
            {
                if (string.IsNullOrEmpty(cmd))                  // 命令为空
                {
                    try
                    {
                        return File.ReadAllText(helppath);
                    }
                    catch (Exception ex)
                    {
                        loger.Error(ex);
                        return "";
                    }
                }
                else {
                    try {
                        string[] lines = File.ReadAllLines(helppath);
                        for (int i=0;i<lines.Length;i++) {
                            if (cmd.Trim().ToLower() == lines[i].Trim().ToLower()) {    // 检索命令
                                sb.AppendLine(lines[i]);
                                if (++i < lines.Length)
                                    sb.AppendLine(lines[i]);
                                if (++i < lines.Length)
                                    sb.AppendLine(lines[i]);
                                break;
                            }
                        }
                        return sb.ToString();
                    }
                    catch (Exception ex) {
                        loger.Error(ex);
                        return "";
                    }
                }
            }
            return "";
        }
        #endregion
    }
}
